home *** CD-ROM | disk | FTP | other *** search
/ Aminet 24 / Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso / Aminet / comm / mail / Mutt089src.lha / Mutt-0.89i-AMIGA / src / postpone.c < prev    next >
C/C++ Source or Header  |  1998-01-28  |  8KB  |  330 lines

  1. /*
  2.  * Copyright (C) 1996-8 Michael R. Elkins <me@cs.hmc.edu>
  3.  * 
  4.  *     This program is free software; you can redistribute it and/or modify
  5.  *     it under the terms of the GNU General Public License as published by
  6.  *     the Free Software Foundation; either version 2 of the License, or
  7.  *     (at your option) any later version.
  8.  * 
  9.  *     This program is distributed in the hope that it will be useful,
  10.  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  *     GNU General Public License for more details.
  13.  * 
  14.  *     You should have received a copy of the GNU General Public License
  15.  *     along with this program; if not, write to the Free Software
  16.  *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  */ 
  18.  
  19. #include "mutt.h"
  20. #include "mutt_menu.h"
  21. #include "send.h"
  22. #include "rfc1524.h"
  23. #include "mime.h"
  24. #include "mailbox.h"
  25. #include "parse.h"
  26.  
  27. #include <ctype.h>
  28. #include <unistd.h>
  29. #include <string.h>
  30. #include <sys/stat.h>
  31.  
  32. static short PostCount = 0;
  33. static time_t LastModify = 0;
  34. static CONTEXT *PostContext = NULL;
  35.  
  36. int mutt_num_postponed (void)
  37. {
  38.   struct stat st;
  39.   CONTEXT ctx;
  40.  
  41.   if (stat (Postponed, &st) == -1)
  42.   {
  43.      PostCount = 0;
  44.      LastModify = 0;
  45.      return (0);
  46.   } 
  47.   else if (S_ISDIR (st.st_mode))
  48.   {
  49.     /* if we have a maildir mailbox, we need to stat the "new" dir */
  50.  
  51.     char buf[_POSIX_PATH_MAX];
  52.  
  53.     snprintf (buf, sizeof (buf), "%s/new", Postponed);
  54.     if (access (buf, F_OK) == 0 && stat (buf, &st) == -1)
  55.     {
  56.       PostCount = 0;
  57.       LastModify = 0;
  58.       return 0;
  59.     }
  60.   }
  61.  
  62.   if (LastModify < st.st_mtime)
  63.   {
  64.     LastModify = st.st_mtime;
  65.  
  66.     if (access (Postponed, R_OK | F_OK) != 0)
  67.       return (PostCount = 0);
  68.     if (mx_open_mailbox (Postponed, M_NOSORT | M_QUIET, &ctx) == NULL)
  69.       PostCount = 0;
  70.     else
  71.       PostCount = ctx.msgcount;
  72.     mx_fastclose_mailbox (&ctx);
  73.   }
  74.  
  75.   return (PostCount);
  76. }
  77.  
  78. static void post_entry (char *s, size_t slen, MUTTMENU *menu, int entry)
  79. {
  80.   char buf[SHORT_STRING] = { 0 };
  81.   CONTEXT *ctx = (CONTEXT *) menu->data;
  82.  
  83.   rfc822_write_address (buf, sizeof (buf), ctx->hdrs[entry]->env->to);
  84.   snprintf (s, slen, "%2d %c %-20.20s     %s",
  85.         entry + 1,
  86.         ctx->hdrs[entry]->deleted ? 'D' : ' ',
  87.         buf,
  88.         ctx->hdrs[entry]->env->subject);
  89. }
  90.  
  91. static HEADER *select_msg (void)
  92. {
  93.   MUTTMENU *menu;
  94.   int i, done=0, r=-1;
  95.   char helpstr[SHORT_STRING];
  96.   char tmp[16];
  97.  
  98.   menu = mutt_new_menu ();
  99.   menu->make_entry = post_entry;
  100.   menu->menu = MENU_POST;
  101.   menu->max = PostContext->msgcount;
  102.   menu->title = "Postponed Messages";
  103.   menu->data = PostContext;
  104.  
  105.   helpstr[0] = 0;
  106.   mutt_make_help (tmp, sizeof (tmp), "Exit  ", MENU_POST, OP_EXIT);
  107.   strcat (helpstr, tmp);
  108.   mutt_make_help (tmp, sizeof (tmp), "Del  ", MENU_POST, OP_DELETE);
  109.   strcat (helpstr, tmp);
  110.   mutt_make_help (tmp, sizeof (tmp), "Undel  ", MENU_POST, OP_UNDELETE);
  111.   strcat (helpstr, tmp);
  112.   mutt_make_help (tmp, sizeof (tmp), "Help", MENU_POST, OP_HELP);
  113.   strcat (helpstr, tmp);
  114.   menu->help = helpstr;
  115.  
  116.   while (!done)
  117.   {
  118.     switch (i = mutt_menuLoop (menu))
  119.     {
  120.       case OP_DELETE:
  121.       case OP_UNDELETE:
  122.     mutt_set_flag (PostContext, PostContext->hdrs[menu->current], M_DELETE, (i == OP_DELETE) ? 1 : 0);
  123.     PostCount = PostContext->msgcount - PostContext->deleted;
  124.     if (option (OPTRESOLVE) && menu->current < menu->max - 1)
  125.     {
  126.       menu->oldcurrent = menu->current;
  127.       menu->current++;
  128.       if (menu->current >= menu->top + menu->pagelen)
  129.       {
  130.         menu->top = menu->current;
  131.         menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
  132.       }
  133.       else
  134.         menu->redraw |= REDRAW_MOTION_RESYNCH;
  135.     }
  136.     else
  137.       menu->redraw = REDRAW_CURRENT;
  138.     break;
  139.  
  140.       case OP_GENERIC_SELECT_ENTRY:
  141.     r = menu->current;
  142.     done = 1;
  143.     break;
  144.  
  145.       case OP_EXIT:
  146.     done = 1;
  147.     break;
  148.     }
  149.   }
  150.  
  151.   mutt_menuDestroy (&menu);
  152.   return (r > -1 ? PostContext->hdrs[r] : NULL);
  153. }
  154.  
  155. /* args:
  156.  *    hdr    envelope/attachment info for recalled message
  157.  *    cur    if message was a reply, `cur' is set to the message which
  158.  *        `hdr' is in reply to
  159.  *
  160.  * return vals:
  161.  *    -1        error/no messages
  162.  *    0        normal exit
  163.  *    SENDREPLY    recalled message is a reply
  164.  */
  165. int mutt_get_postponed (HEADER *hdr, HEADER **cur)
  166. {
  167.   HEADER *h;
  168.   MESSAGE *msg;
  169.   int code = SENDPOSTPONED;
  170.   LIST *tmp;
  171.   LIST *last = NULL;
  172.   LIST *next;
  173.   char file[_POSIX_PATH_MAX];
  174.   char *p;
  175.   int opt_delete;
  176.  
  177.   if ((PostContext = mx_open_mailbox (Postponed, M_NOSORT, NULL)) == NULL)
  178.   {
  179.     PostCount = 0;
  180.     mutt_error ("No postponed messages.");
  181.     return (-1);
  182.   }
  183.   
  184.   if (! PostContext->msgcount)
  185.   {
  186.     PostCount = 0;
  187.     mx_close_mailbox (PostContext);
  188.     safe_free ((void **) &PostContext);
  189.     mutt_error ("No postponed messages.");
  190.     return (-1);
  191.   }
  192.  
  193.   if (PostContext->msgcount == 1)
  194.   {
  195.     /* only one message, so just use that one. */
  196.     h = PostContext->hdrs[0];
  197.   }
  198.   else if ((h = select_msg ()) == NULL)
  199.   {
  200.     mx_close_mailbox (PostContext);
  201.     safe_free ((void **) &PostContext);
  202.     return (-1);
  203.   }
  204.  
  205.   if ((msg = mx_open_message (PostContext, h->msgno)) == NULL)
  206.   {
  207.     mx_close_mailbox (PostContext);
  208.     safe_free ((void **) &PostContext);
  209.     return (-1);
  210.   }
  211.  
  212.   fseek (msg->fp, h->offset, 0);
  213.   hdr->env = mutt_read_rfc822_header (msg->fp, NULL);
  214.  
  215.   if (h->content->type == TYPEMESSAGE || h->content->type == TYPEMULTIPART)
  216.   {
  217.     BODY *b;
  218.  
  219.     fseek (msg->fp, h->content->offset, 0);
  220.  
  221.     if (h->content->type == TYPEMULTIPART)
  222.     {
  223.       h->content->parts = mutt_parse_multipart (msg->fp, 
  224.            mutt_get_parameter ("boundary", h->content->parameter),
  225.            h->content->offset + h->content->length,
  226.            strcasecmp ("digest", h->content->subtype) == 0);
  227.     }
  228.     else
  229.       h->content->parts = mutt_parse_messageRFC822 (msg->fp, h->content);
  230.  
  231.     /* Now that we know what was in the other message, convert to the new
  232.      * message.
  233.      */
  234.     hdr->content = h->content->parts;
  235.     b = h->content->parts;
  236.     while (b != NULL)
  237.     {
  238.       file[0] = '\0';
  239.       if (b->filename)
  240.     strfcpy (file, b->filename, sizeof (file));
  241.       mutt_adv_mktemp (file);
  242.       if (mutt_save_attachment (msg->fp, b, file, 0) == -1)
  243.       {
  244.     mutt_free_envelope (&hdr->env);
  245.     mutt_free_body (&hdr->content);
  246.     mx_close_message (&msg);
  247.     mx_fastclose_mailbox (PostContext);
  248.     safe_free ((void **) &PostContext);
  249.     return (-1);
  250.       }
  251.       safe_free ((void *) &b->filename);
  252.       b->filename = safe_strdup (file);
  253.       b->unlink = 1;
  254.       mutt_free_body (&b->parts);
  255.       b = b->next;
  256.     }
  257.     h->content->parts = NULL;
  258.   }
  259.   else
  260.   {
  261.     mutt_mktemp (file);
  262.     if (mutt_save_attachment (msg->fp, h->content, file, 0) == -1)
  263.     {
  264.       mutt_free_envelope (&hdr->env);
  265.       mx_close_message (&msg);
  266.       mx_fastclose_mailbox (PostContext);
  267.       safe_free ((void **) &PostContext);
  268.       return (-1);
  269.     }
  270.     hdr->content = mutt_make_attach (file);
  271.     hdr->content->use_disp = 0;    /* no content-disposition */
  272.     hdr->content->unlink = 1;    /* delete when we are done */
  273.   }
  274.  
  275.   mx_close_message (&msg);
  276.  
  277.   /* finished with this message, so delete it. */
  278.   mutt_set_flag (PostContext, h, M_DELETE, 1);
  279.  
  280.   /* update the count for the status display */
  281.   PostCount = PostContext->msgcount - PostContext->deleted;
  282.  
  283.   /* avoid the "purge deleted messages" prompt */
  284.   opt_delete = quadoption (OPT_DELETE);
  285.   set_quadoption (OPT_DELETE, M_YES);
  286.   mx_close_mailbox (PostContext);
  287.   set_quadoption (OPT_DELETE, opt_delete);
  288.  
  289.   safe_free ((void **) &PostContext);
  290.  
  291.   for (tmp = hdr->env->userhdrs; tmp; )
  292.   {
  293.     if (Context && strncmp ("X-Mutt-References:", tmp->data, 18) == 0)
  294.     {
  295.       int j;
  296.  
  297.       p = tmp->data + 18;
  298.       SKIPWS (p);
  299.  
  300.       for (j=0; j < Context->msgcount; j++)
  301.       {
  302.     if (Context->hdrs[j]->env->message_id &&
  303.         strcmp (Context->hdrs[j]->env->message_id, p) == 0)
  304.     {
  305.       *cur = Context->hdrs[j];
  306.       break;
  307.     }
  308.       }
  309.  
  310.       /* Remove the X-Mutt-References: header field. */
  311.       next = tmp->next;
  312.       if (last)
  313.     last->next = tmp->next;
  314.       else
  315.     hdr->env->userhdrs = tmp->next;
  316.       tmp->next = NULL;
  317.       mutt_free_list (&tmp);
  318.       tmp = next;
  319.       if (*cur)
  320.     code |= SENDREPLY;
  321.     }
  322.     else
  323.     {
  324.       last = tmp;
  325.       tmp = tmp->ne